using System;

namespace ParboiledSharp.parboiled.dataobjects
{
    public class Context
    {
        private ValueStackList _stackList;
        private char[] _stream;
        private int _currentStreamIndex;
        private int _matchStartPosition;
        private int _matchLength;
        private bool _invert = false;
        private int _lastIterationCount;

        public Context()
        {
            _stackList = new ValueStackList();
        }

        public int getlastIterationsCount() {
            return _lastIterationCount;
        }

        public void SetlastIterationsCount(int lastIterationsCount)
        {
            _lastIterationCount=lastIterationsCount;
        }

        public bool IsInvert() {
            return _invert;
        }

        public void SetInvert(bool invert)
        {
            _invert=invert;
        }

        public void ClearStackList() {
            GetStacksList().Clear();
        }

        public void SetStream(String stream, bool clearContext)
        {
            _stream = stream.ToCharArray();
            _currentStreamIndex = 0;
            SetMatch(0, 0);
            if (clearContext)
            {
                _stackList = new ValueStackList();
            }
        }

        private ValueStackList GetStacksList()
        {
            return _stackList;
        }

        public ValueStack GetStack()
        {
            return GetStacksList().PeekValueStack();
        }

        public void Push(object value) {
            GetStack().Push(value);
        }

        public object Pop()
        {
            return GetStack().Pop();
        }

        public object Pop(int position)
        {
            ValueStack st = GetStack();
            return st.Pop(position);
        }

        public string PopObjectWithThePrefix(string prefix)
        {
            ValueStack st = GetStack();
            return st.PopStringWithThePrefix(prefix);
        }

        public void InLevel()
        {
            GetStacksList().CloneValueStack();
        }

        public void OutLevel(bool saveValueStack)
        {
            if (saveValueStack)
            {
                GetStacksList().PopButSaveLastValueStack();
            }
            else
            {
                GetStacksList().DiscardValueStack();
            }
        }

        public int GetCurrentStreamIndex()
        {
            return _currentStreamIndex;
        }

        public void SetCurrentStreamIndex(int currentStreamIndex)
        {
            _currentStreamIndex = currentStreamIndex;
        }

        public bool EOL()
        {
            if (GetCurrentStreamIndex() >= _stream.Length)
            {
                return true;
            }

            return false;
        }

        public char GetNextChar()
        {
            if (_currentStreamIndex >= _stream.Length)
            {
                return (char)0;
            }

            char c = _stream[_currentStreamIndex];
            _currentStreamIndex++;
            return c;
        }

        private int GetMatchStartPosition()
        {
            return _matchStartPosition;
        }

        private int GetMatchLength()
        {
            return _matchLength;
        }

        public void SetMatch(int startPosition, int length)
        {
            _matchStartPosition = startPosition;
            _matchLength = length;
        }

        public string GetMatch()
        {
            return new string(_stream, GetMatchStartPosition(), GetMatchLength());
        }
    }
}
